# @Author   : tan90
# @Time     : 2025/1/25 08:58
import json
import math
import random
import signal
import sys
import time
from concurrent.futures.thread import ThreadPoolExecutor
from datetime import datetime

import paho.mqtt.client as mqtt

# 连接信息
client_id = f"python_rower_{random.randint(1000, 9999)}"
port = 1883
clean_session = True
keepalive = 5

host = "test.ironmanapi.com"
username = "admin"
password = "nttieren0513"

product_code = "v5lzawg6"

users = [
    {
        "userKey": "12341234",
        "divisor": 2,
        "deviceCode": "B4607739931A"
    },
    {
        "userKey": "wn",
        "divisor": 1,
        "deviceCode": "B4607739931B"
    },
]

stop_flag = False
pool = ThreadPoolExecutor(max_workers=len(users))


def mock_sport_event(client, user_key: str, device_code: str):
    login_event_data = {
        "data": {
            "eventCode": "info_01",
            "eventType": "info",
            "eventValue": {
                "currentStatus": "02",
                "preStatus": "04",
                "sportModeName": "快速开始"
            }
        },
        "deviceCode": device_code,
        "ts": f"{datetime.now().strftime("%Y%m%d%H%M%S%f")[:17]}",
        "user": {
            "userKey": user_key
        }
    }
    topic = f"thing/up/event/{product_code}/{device_code}"
    res: mqtt.MQTTMessageInfo = client.publish(topic, payload=json.dumps(login_event_data), qos=1)
    print(f"mock_login_event {user_key} mid:{res.mid} rc:{res.rc}")


def mock_instant_data(client, user_key: str, divisor: int, device_code: str):
    sleep_seconds = 0.2
    distance = 0
    frequency = 0
    speed = 0
    power = 0
    calorie = 0
    timePer500m = 0
    time_seconds = 0
    topic = f"thing/up/property/{product_code}/{device_code}"

    while not stop_flag:
        instant_data = {
            "data": {
                "dataType": "instant",
                "distance": distance,
                "frequency": frequency,
                "speed": speed,
                "power": power,
                "calorie": round(calorie, 1),
                "timePer500m": timePer500m,
                "sportMode": "1",
                "time": math.floor(time_seconds)
            },
            "ts": f"{datetime.now().strftime("%Y%m%d%H%M%S%f")[:17]}",
            "deviceCode": device_code,
            "user": {
                "userKey": user_key
            }
        }
        time.sleep(sleep_seconds)
        res: mqtt.MQTTMessageInfo = client.publish(topic, payload=json.dumps(instant_data), qos=1)
        distance += random.randint(2, 3)
        frequency = random.randint(40, 50)
        speed = random.randint(30, 45) * divisor
        power = random.randint(300, 500)
        calorie += random.uniform(0.5, 1.0) * divisor
        timePer500m = random.randint(200, 300)
        time_seconds += sleep_seconds
        print(f"mock_instant_data {user_key} mid:{res.mid} rc:{res.rc} {instant_data['data']['distance']}")


def do_mock(client, user_key: str, divisor: int, device_code: str):
    time.sleep(3)
    mock_sport_event(client, user_key, device_code)
    time.sleep(3)
    mock_instant_data(client, user_key, divisor, device_code)


def on_connect(client, userdata, flags, rc):
    if rc == 0:
        # 订阅主题
        print(f"【{host} {port}】mqtt客户端连接成功")
        for user in users:
            pool.submit(do_mock, mqtt_client, user["userKey"], user["divisor"], user["deviceCode"])


def on_disconnect(client, userdata, rc):
    print(f"【{host} {port}】mqtt客户端断开连接 {rc}")


mqtt_client = mqtt.Client(client_id=client_id, clean_session=clean_session)
mqtt_client.username_pw_set(username, password)
mqtt_client.on_connect = on_connect
mqtt_client.on_disconnect = on_disconnect
mqtt_client.connect(host, port, keepalive)


def signal_handler(signum, frame):
    print(f"正在关闭 MQTT 客户端...")
    global stop_flag
    stop_flag = True
    print("正在关闭线程池...")
    pool.shutdown()
    mqtt_client.loop_stop()
    mqtt_client.disconnect()
    sys.exit(0)


signal.signal(signal.SIGINT, signal_handler)

# 保持网络循环，等待消息
mqtt_client.loop_forever()
